//
//  NotewokeTools.swift
//  Weibo
///Users/apple/Desktop/Swift入门/Swift代码/第三天/Weibo/Weibo/Weibo/Classes/Tools/Extension/NetwokeTools.swift:98:61: Cannot convert value of type '(NSURLSessionDataTask, AnyObject) -> Void' to expected argument type '((NSURLSessionDataTask, AnyObject?) -> Void)?'
//  Created by apple on 15/12/8.
//  Copyright © 2015年 idcast. All rights reserved.
//

import UIKit

import AFNetworking

//定义个枚举
enum HMRequestMethod: String {

    case GET = "GET"
    case POST = "POST"
}
class NetwokeTools: AFHTTPSessionManager {
    //应用程序信息
    private let appKey = "679789651"
    private let appSecret = "363af57defe1e6027f8154dd3294f4b6"
    private let redirectUrl = "http://www.baidu.com"
    
    /// 网络请求完成回调，类似于 OC 的 typeDefine
    typealias HMRequestCallBack = (result: AnyObject?, error: NSError?)->()
    
    //单例
    static let sharedTools: NetwokeTools = {
    
        let tools = NetwokeTools(baseURL: nil)
        //设置反序列化格式
        tools.responseSerializer.acceptableContentTypes?.insert("text/plain")
        return tools
    }()
    /// 返回 token 字典
    private var tokenDict: [String: AnyObject]? {
        // 判断 token 是否有效
        if let token = UserAccountViewModel.sharedUserAccount.accessToken {
            
            return ["access_token": token]
        }
        
        return nil
    }
}

//MARK： 发布微博

extension NetwokeTools {

    func sendStatus(status: String, image: UIImage?, finished: HMRequestCallBack) {
    
        //1 创建参数字典
        var params = [String: AnyObject]()
        
        //2 设置参数
        params["status"] = status
        
        //3 判断是否上传图片
        if image == nil {
        
            let urlString = "https://api.weibo.com/2/statuses/update.json"
            
            tokenRequest(.POST, URLString: urlString, parameters: params, finished: finished)
            
        }else {
        
            let urlString = "https://upload.api.weibo.com/2/statuses/upload.json"
            let data = UIImagePNGRepresentation(image!)
            upload(urlString, data: data!, name: "pic", parameters: params, finished: finished)
        }
        
    }
}
//MARK: 微博数据相关方法
extension NetwokeTools {

    func loadStatus(since_id since_id: Int, max_id: Int, finished: HMRequestCallBack) {
    
        //获取token字典
        guard var params = tokenDict else {
        
            //如果token为nil 通知掉用放 token无效
            finished(result: nil, error: NSError(domain: "cn.itcast.error", code: -1001, userInfo: ["message": "token为空"]))
            return
        }
        // 判断是否下拉
        if since_id > 0 {
            params["since_id"] = since_id
        } else if max_id > 0 {  // 上拉参数
            params["max_id"] = max_id - 1
        }

        //准备网络参数
        let urlString = "https://api.weibo.com/2/statuses/home_timeline.json"
        
        //发起网络请求
        request(.GET, URLString: urlString, parameters: params, finished: finished)
    }
}
// MARK: - 用户相关方法
extension NetwokeTools {
    
    /// 加载用户信息
    ///
    /// - parameter uid:         uid
    /// - parameter finished:    完成回调
    /// - see: [http://open.weibo.com/wiki/2/users/show](http://open.weibo.com/wiki/2/users/show)
    func loadUserInfo(uid: String, finished: HMRequestCallBack) {
        
        // 1. 获取 token 字典
        guard var params = tokenDict else {
            
            // 如果字典为 nil，通知调用方，token 无效
            finished(result: nil, error: NSError(domain: "cn.itcast.error", code: -1001, userInfo: ["message": "token 为空"]))
            
            return
        }
        
        // 2. 处理网络参数
        let urlString = "https://api.weibo.com/2/statuses/home_timeline.json"
        //https://api.weibo.com/2/statuses/home_timeline.json?access_token=2.00YBub_G6dP8NE0af5d5b2030IPC_y&uid=5786580872
        params["uid"] = uid
        print("params\(params)")
        
        request(.GET, URLString: urlString, parameters: params, finished: finished)
    }
}


//MARK 加载用户信息
extension NetwokeTools {

    func loadUserInfo(uid: String, access_token: String, finished: HMRequestCallBack) {
    
        let urlString = "https://api.weibo.com/2/users/show.json"
        
        let params = ["uid": uid,
        "access_token":access_token]
        
        request(.GET, URLString: urlString, parameters: params, finished: finished)
    }
}

//MARK: OAuth 相关方法

extension NetwokeTools {

    //OAuth 授权URL
    
    var oauthURL: NSURL {
    
    
        let urlString = "https://api.weibo.com/oauth2/authorize?client_id=\(appKey)&redirect_uri=\(redirectUrl)"
        return NSURL(string: urlString)!
    }
    //加载AccessToken
    func loadAccessToken(code: String, finished: HMRequestCallBack) {
    
        let urlString = "https://api.weibo.com/oauth2/access_token"
        print(appKey)
        print(appSecret)
        print(code)
        print(redirectUrl)
        let params = ["client_id": appKey,
            "client_secret": appSecret,
            "grant_type": "authorization_code",
            "code": code,
            "redirect_uri": redirectUrl]
//        let params = ["client_id": appKey,
//            "client_secret": appSecret,
//            "grant_type": "authorization_code",
//            "code": code,
//            "redirect_uri": redirectUrl]
        
        request(.POST, URLString: urlString, parameters: params, finished: finished)
    }
}




//MARK: 封装AFN网络的方法
extension NetwokeTools {
    
    /// 向 parameters 字典中追加 token 参数
    ///
    /// - parameter parameters: 参数字典
    ///
    /// - returns: 是否追加成功
    /// - 默认情况下，关于函数参数，在调用时，会做一次 copy，函数内部修改参数值，不会影响到外部的数值
    /// - inout 关键字，相当于在 OC 中传递对象的地址
    private func appendToken(inout parameters: [String: AnyObject]?) -> Bool {
        
        // 1> 判断 token 是否为nil
        guard let token = UserAccountViewModel.sharedUserAccount.accessToken else {
            return false
        }
        
        // 2> 判断参数字典是否有值
        if parameters == nil {
            parameters = [String: AnyObject]()
        }
        
        // 3> 设置 token
        parameters!["access_token"] = token
        
        return true
    }
    
    /// 使用 token 进行网络请求
    ///
    /// - parameter method:     GET / POST
    /// - parameter URLString:  URLString
    /// - parameter parameters: 参数字典
    /// - parameter finished:   完成回调
    private func tokenRequest(method: HMRequestMethod, URLString: String, var parameters: [String: AnyObject]?, finished: HMRequestCallBack) {
        
        // 1> 如果追加 token 失败，直接返回
        if !appendToken(&parameters) {
            finished(result: nil, error: NSError(domain: "cn.itcast.error", code: -1001, userInfo: ["message": "token 为空"]))
            
            return
        }
        
        // 2. 发起网络请求
        request(method, URLString: URLString, parameters: parameters, finished: finished)
    }

    func request(method:HMRequestMethod, URLString: String, parameters: [String: AnyObject]?, finished:(result: AnyObject?, error: NSError?) ->()) {
        //定义成功回调
        let success = { (task: NSURLSessionDataTask, result: AnyObject?) -> Void in
        
            finished(result: result, error: nil)
        }
        //定义回调失败   加个问号
        let failuer = { (task: NSURLSessionDataTask?, error: NSError) -> Void in
             print(error)
            finished(result: nil, error: error)
        }
        
//        self.GET(URLString, parameters: parameters, progress: nil, success: success, failure: failuer)
        
        if method == HMRequestMethod.GET {
        
           GET(URLString, parameters: parameters, progress: nil, success: success, failure: failuer)
        }else if method == HMRequestMethod.POST {
        
            POST(URLString, parameters: parameters, progress: nil, success: success, failure: failuer)
        }
    }
    /// 上传文件
    private func upload(URLString: String, data: NSData, name: String, var parameters: [String: AnyObject]?, finished: HMRequestCallBack) {
        
        // 1> 如果追加 token 失败，直接返回
        if !appendToken(&parameters) {
            finished(result: nil, error: NSError(domain: "cn.itcast.error", code: -1001, userInfo: ["message": "token 为空"]))
            
            return
        }
        
        /**
        1. data 要上传文件的二进制数据
        2. name 是服务器定义的字段名称 － 后台接口文档会提示
        3. fileName 是保存在服务器的文件名，但是：现在通常可以`乱写`，后台会做后续的处理
        - 根据上传的文件，生成 缩略图，中等图，高清图
        - 保存在不同路径，并且自动生成文件名
        
        - fileName 是 HTTP 协议定义的属性
        4. mimeType / contentType: 客户端告诉服务器，二进制数据的准确类型
        - 大类型/小类型
        * image/jpg image/gif image/png
        * text/plain text/html
        * application/json
        - 无需记忆
        - 如果不想告诉服务器准确的类型
        * application/octet-stream
        */
        POST(URLString, parameters: parameters, constructingBodyWithBlock: { (formData) -> Void in
            
            formData.appendPartWithFileData(data, name: name, fileName: "xxx", mimeType: "application/octet-stream")
            
            }, success: { (_, result) -> Void in
                finished(result: result, error: nil)
            }) { (_, error) -> Void in
                print(error)
                finished(result: nil, error: error)
        }
    }



}

